package ru.ifmo.genetics.mutation;

import org.uncommons.maths.number.NumberGenerator;
import org.uncommons.maths.random.Probability;
import org.uncommons.watchmaker.framework.EvolutionaryOperator;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * @author avhaliullin
 */
public abstract class AbstractMutation<T> implements EvolutionaryOperator<T> {
    private final NumberGenerator<Probability> mutationProbability;

    public AbstractMutation(NumberGenerator<Probability> mutationProbability) {
        this.mutationProbability = mutationProbability;
    }

    public List<T> apply(List<T> selectedCandidates, Random rng) {
        List<T> result = new ArrayList<T>();
        for (T individual : selectedCandidates)
            if (mutationProbability.nextValue().nextEvent(rng)) {
                result.add(mutate(individual, rng));
            } else {
                result.add(individual);
            }
        return result;
    }

    protected abstract T mutate(T individual, Random rng);
}
